/*
 *    BinaryFileStream.java
 *    Copyright (C) 2007 University of Waikato, Hamilton, New Zealand
 *    @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package moa.streams;

import java.io.BufferedReader;

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import moa.core.InputStreamProgressMonitor;
import moa.core.InstancesHeader;
import moa.core.ObjectRepository;
import moa.learners.VPSP;
import moa.options.AbstractOptionHandler;
import moa.options.FileOption;
import moa.options.FloatOption;
import moa.options.IntOption;
import moa.tasks.TaskMonitor;

import weka.core.Attribute;
import weka.core.FastVector;
import weka.core.Instance;
import weka.core.Instances;

import moa.learners.VPSP;

public class BinaryFileStream extends AbstractOptionHandler implements
		InstanceStream {

	@Override
	public String getPurposeString() {
		return "A stream read from an binary file.";
	}
	
	private static final long serialVersionUID = 1L;

	public FileOption binaryFileOption = new FileOption("data", 'f',
			"Binary file to load.", null, "data", false);

	public IntOption classIndexOption = new IntOption(
			"classIndex",
			'c',
			"Class index of data. 0 for none or -1 for last attribute in file.",
			-1, -1, Integer.MAX_VALUE);
	public IntOption treeRandomSeedOption = new IntOption("treeRandomSeed",
			'r', "Seed for random generation of tree.", 1);

	public IntOption instanceRandomSeedOption = new IntOption(
			"instanceRandomSeed", 'i',
			"Seed for random generation of instances.", 1);

	public IntOption numNominalsOption = new IntOption("numNominals", 'o',
			"The number of nominal attributes to generate.", 4, 0,
			Integer.MAX_VALUE);

	public IntOption numNumericsOption = new IntOption("numNumerics", 'u',
			"The number of numeric attributes to generate.", 0, 0,
			Integer.MAX_VALUE);

	protected InstancesHeader streamHeader;

	protected Instances instances;

	protected Reader fileReader;

	protected boolean hitEndOfFile;

	protected Instance lastInstanceRead;

	protected int numInstancesRead;
	
    public int  i_data ;
    
    public DataInputStream data_in;
    
    public int numberInstances ;
    
    public int firstItem;
    


	protected InputStreamProgressMonitor fileProgressMonitor;

	public BinaryFileStream() {

	}

	public BinaryFileStream(String binaryFileName, int classIndex) {
		this.binaryFileOption.setValue(binaryFileName);
		this.classIndexOption.setValue(classIndex); 
		restart();
	}

	@Override
	public void prepareForUseImpl(TaskMonitor monitor,
			ObjectRepository repository) {
		generateHeader();
		restart();
		System.out.println ("Try it " + this.binaryFileOption.getFile().getPath());
		//VPSP vpsp = new VPSP(this.binaryFileOption.getFile().getPath(),0.5);
	}
	
	protected void generateHeader() {
		/*
		FastVector attributes = new FastVector();
		FastVector nominalAttVals = new FastVector();
		for (int i = 0; i < this.numNominalsOption.getValue(); i++) {
			attributes.addElement(new Attribute("nominal" + (i + 1),
					nominalAttVals));
		}
		for (int i = 0; i < this.numNumericsOption.getValue(); i++) {
			attributes.addElement(new Attribute("numeric" + (i + 1)));
		}
		this.streamHeader = new InstancesHeader(new Instances(
				getCLICreationString(InstanceStream.class), attributes, 0));
		this.streamHeader.setClassIndex(this.streamHeader.numAttributes() - 1);*/
	}

	public InstancesHeader getHeader() {
		System.out.println("get Header" + this.streamHeader);
		return this.streamHeader;
		//return new InstancesHeader(this.instances);
	}
	
	public Instances getInstances()
	{
		return this.instances;
	}

	public long estimatedRemainingInstances() {
		/*
		double progressFraction = this.fileProgressMonitor
				.getProgressFraction();
		if ((progressFraction > 0.0) && (this.numInstancesRead > 0)) {
			return (long) ((this.numInstancesRead / progressFraction) - this.numInstancesRead);
		}*/
		return -1;
	}

	public boolean hasMoreInstances() {
		return !this.hitEndOfFile;
	}

	public Instance nextInstance() {
		/*
		double[] attVals = new double[this.numNominalsOption.getValue()
		              				+ this.numNumericsOption.getValue()];
		InstancesHeader header = getHeader();
		Instance inst = new Instance(header.numAttributes());
		for (int i = 0; i < attVals.length; i++) {
			inst.setValue(i,"25");// PROBLEM
		}
		inst.setDataset(header);
		inst.setClassValue("2");
		return inst;
		*/
		return null;
	}

	public boolean isRestartable() {
		return true;
	}

	public void restart() {
		/*
	    FileInputStream file_input = null;
		try {
			file_input = new FileInputStream (this.binaryFileOption
			.getFile());
			data_in    = new DataInputStream (file_input );
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println("restart!");
  		byte type[] = new byte[4];
  	 	for(int i=0; i<4;i++) {
  		     try {
				type[i] = data_in.readByte();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
  		}
  		i_data=(((type[3] & 0xff) << 24) | ((type[2] & 0xff) << 16) |
   			 ((type[1] & 0xff) << 8) | (type[0] & 0xff));
      	if (i_data == -2) {
      			// separator between two customers 
      		numberInstances ++;
		        firstItem = 0;
      	}
      	else if (i_data == -1) {
      		// To separate the sequences
      		System.out.printf (" \n");
      		firstItem = 0;
      	}
      	else      	
      	{
      		// numbers of the sequence
      		if (firstItem == 0)
      		{
      			System.out.printf (numberInstances + " , ");
      			firstItem ++;
      		}
      		System.out.printf ("%d , ", i_data );
      	}
      
		if (this.classIndexOption.getValue() < 0) {
			this.instances.setClassIndex(this.instances.numAttributes() - 1);
		} else if (this.classIndexOption.getValue() > 0) {
			this.instances.setClassIndex(this.classIndexOption.getValue() - 1);
		}
		*/

	}


	public void getDescription(StringBuilder sb, int indent) {
		// TODO Auto-generated method stub

	}

/*

	
	
 */
	
}
